// Copyright 2012 Google Inc. All rights reserved.
package collector

import (
	"fmt"
	"strings"
	"time"
)

const (
	defaultInterval = time.Minute * 10
)

type varAgg struct {
	name string
	agg  string
}

type feedVar struct {
	source string
	vars   []varAgg
}

type feedRequest struct {
	end      time.Time
	duration time.Duration
	vars     []feedVar
	interval time.Duration
}

// source1;var1!rate,var2!avg+source2;var3,var4
func parseFeedVars(fReq *feedRequest, spec string) error {
	parts := strings.Split(spec, "+")
	for _, s := range parts {
		ps := strings.Split(s, ";")
		if len(ps) != 2 {
			return fmt.Errorf("invalid feed variables spec %q", spec)
		}
		source, varNames := ps[0], ps[1]
		vs := strings.Split(varNames, ",")
		fvar := feedVar{source: source}
		for _, v := range vs {
			flds := strings.SplitN(v, "!", 2)
			switch len(flds) {
			case 2:
				fvar.vars = append(fvar.vars, varAgg{name: flds[0], agg: flds[1]})
			case 1:
				fvar.vars = append(fvar.vars, varAgg{name: flds[0]})
			}
		}
		fReq.vars = append(fReq.vars, fvar)
	}
	return nil
}

// /source1;var1!rate,var2!avg+source2;var3,var4@5m/endTime/duration
func parseFeedUrl(u string) (*feedRequest, error) {
	parts := strings.Split(u, "/")
	// TODO support a default series start and length?
	if len(parts) != 5 {
		return nil, fmt.Errorf("length of path %q is too short", u)
	}
	varSpec, dateSpec, duration := parts[2], parts[3], parts[4]
	var end time.Time
	var err error
	if dateSpec == "now" {
		end = time.Now()
	} else {
		end, err = time.Parse(layout, dateSpec)
		if err != nil {
			return nil, fmt.Errorf("Unable to parse startDate %q", err)
		}
	}
	dur, err := time.ParseDuration(duration)
	if err != nil {
		return nil, fmt.Errorf("Unable to parse duration %q", err)
	}
	fReq := &feedRequest{end: end, duration: dur, interval: defaultInterval}
	rateParts := strings.Split(varSpec, "@")
	if len(rateParts) == 2 {
		if fReq.interval, err = time.ParseDuration(rateParts[1]); err != nil {
			return nil, fmt.Errorf("Invalid interval %q for aggregations %s", rateParts[1], err)
		}
	} else if len(rateParts) > 2 {
		return nil, fmt.Errorf("Too many aggregation intervals")
	}
	for _, source := range strings.Split(rateParts[0], "+") {
		err = parseFeedVars(fReq, source)
		if err != nil {
			return nil, err
		}
	}
	return fReq, nil
}
